课程主页:

https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-172-performance-engineering-of-software-systems-fall-2018/index.htm

课程视频:

https://www.bilibili.com/video/BV1wA411h7N7

这次回顾第四讲,这一讲介绍了汇编语言以及计算机体系结构。

备注:由于这次内容比较多,所以分为两次回顾,这次先回顾X86-64 ISA PRIMER以及FLOATING-POINT AND VECTOR HARDWARE。

源代码到执行

从源代码到执行一共分为四个阶段:

  1. 预处理(Preprocessing)
  2. 编译(Compiling)
  3. 汇编(Assembling)
  4. 链接(Linking)

步骤1,2如下图所示:

汇编语言提供了方便的机器代码符号表示。

反汇编

对于二进制文件,可以利用反汇编指令得到汇编代码:

objdump -S fib

得到如下结果:

学习汇编的意义

为什么要看程序的汇编代码呢?

  • 该程序集显示了编译器做了什么和没有做什么。
  • 漏洞可能会在较低级别出现。 例如,代码中的错误仅在–O3编译时才有效。 此外,有时编译器是漏洞的根源!
  • 当所有其他方法均失败时,可以手动修改汇编代码。
  • 逆向工程:当只能访问程序的二进制文件时,可以解密程序的工作。

X86-64 ISA PRIMER

这部分可以参考之前整理的资料,这里只补充之前不熟悉的部分:

https://doraemonzzz.com/2020/05/18/CMU%2015-213%20Intro%20to%20Computer%20Systems%20Lecture%205/

https://doraemonzzz.com/2020/05/19/CMU%2015-213%20Intro%20to%20Computer%20Systems%20Lecture%206/

x86-64常用寄存器

x86-64数据类型

后缀的含义

RFLAGS寄存器

算术和逻辑运算会更新RFLAGS寄存器中的状态标志,全部状态如下:

几个具体例子:

  • CF:最后一个ALU运算从最高有效位产生进位或借位。
  • ZF:上一次ALU运算的结果为0。
  • SF:最后一个ALU操作产生一个其符号位已设置的值。
  • OF:最后一个ALU操作导致算术溢出。

FLOATING-POINT AND VECTOR HARDWARE

浮点数指令集

现代的x86-64架构通过几个不同的指令集支持标量(即非矢量)浮点运算。

  • SSE和AVX指令支持单精度和双精度标量浮点数算法,即“float”和“double”。
  • x87指令支持单精度,双精度和扩展精度标量浮点运算,即“float”,“double”和“long double”。

SSE和AVX指令集还包括向量指令。

标量浮点的SSE

编译器比x87指令更喜欢使用SSE指令,因为SSE指令更易于编译和优化。

  • SSE用于浮点值的操作码类似于x86_64操作码。
  • SSE操作数使用XMM寄存器和浮点类型。

SSE操作码后缀

SSE指令使用两个字母的后缀来编码数据类型:

备注:

  • 第一个字母single或packed(即vector)
  • 第二个字母区分single-precision或double-precision

Vector Hardware

现代微处理器通常结合向量硬件,以单指令流,多数据流(SIMD)的方式处理数据。

  • 令$k$表示向量宽度。
  • 每个向量寄存器保存$k$个标量整数或浮点值。
  • 该单元包含$k$个向量通道,每个通道包含标量整数或浮点硬件。
  • 所有向量通道均以固定步长运行,并使用相同的指令和控制信号。

向量指令

向量指令通常以元素方式运行:

  • 一个向量寄存器的第$i$个元素只能与其他向量寄存器的第$i$个元素一起参与运算。
  • 所有通道对向量的各个元素执行完全相同的操作。
  • 根据体系结构,向量内存操作数可能需要对齐,这意味着它们的地址必须是向量宽度的倍数。
  • 一些架构支持跨通道操作,例如插入或提取向量元素的子集,对向量进行排列(也称为改组),分散或聚集。

向量指令集

现代的x86-64体系结构支持多个向量指令集。

  • 现代的SSE指令集支持对整数,单精度和双精度浮点值进行向量运算。
  • AVX指令支持对单精度和双精度浮点值进行向量运算。
  • AVX2指令将整数向量运算添加到AVX指令集。
  • AVX-512(AVX3)指令将寄存器长度增加到512位,并提供了新的向量运算,包括popcount。(在Haswell上不可用。)

SSE Versus AVX and AVX2

AVX和AVX2指令集以几种方式扩展了SSE指令集。

  • SSE指令使用128位XMM向量寄存器,并且一次最多可操作2个操作数。
  • AVX指令还可以使用256位YMM向量寄存器,并且一次可以对3个操作数进行操作:两个源操作数和一个不同的目标操作数。

AVX指令:

vaddpd %ymm0, %ymm1, %ymm2

SSE和AVX向量操作码

许多SSE和AVX操作码与传统的x86-64操作码相似,但有细微差别:

向量寄存器别名

像通用寄存器一样,XMM和YMM向量寄存器也是别名。